package charts ;

import flash.events.Event;
import flash.events.MouseEvent;
import charts.series.Element;
import string.Utils;
import flash.display.BlendMode;
import flash.display.Sprite;

import charts.series.dots.DefaultDotProperties;
import charts.series.dots.DotFactory;
import ColorConverter.Color;

class Line extends Base
{
	// JSON style:
		var style: Dynamic;
		var props:Properties;
	
	public function new ( json: Dynamic ) {
		super();		
		
		this.style = /*{
			values: 		[],
			width:			2,
			color: 		'#3030d0',
			text: 			'',		// <-- default not display a key
			'font-size': 	12,
			tip:			'#val#',
			'line-style':	new LineStyle( json['line-style'] ),
			loop:			false,
			axis:			'left'
			// HACK: fix this (remove the merge below)
		};*/

		{
			values: 		[],
			width:			2,
			color: 			Hex('#3030d0'),
			text: 			'',		// <-- default not display a key
			font_size:	 	12,
			tip:			'#val#',
			line_style:		new LineStyle(Reflect.field(json,'line-style')),
			loop:			false,
			axis:			'left'
			// HACK: fix this (remove the merge below)
		};
		
		// hack: keep this incase the merge kills it, we'll
		// remove the merge later (and this hack)
		var tmp: Dynamic = Reflect.field(json,'dot-style');
		
		ObjectHelper.merge_2( json, this.style );
		
		this.props = new DefaultDotProperties( tmp, this.style.color, this.style.axis);
		
		//this.style.color = string.Utils.get_color( this.style.color );
		
		this.key = this.style.text;
		this.font_size	= this.style.font_size; // this.style['font-size']
		
		this.values = this.style.values;
		this.add_values();

		//
		// this allows the dots to erase part of the line
		//
		this.blendMode = BlendMode.LAYER;
		
	}
	
	//
	// called from the BaseLine object
	//
		override function get_element( index: Int, value: Dynamic ): Element {

		if (Std.is(value,Float))
			value = { value:value };
			
		var tmp:Properties = new Properties( value, this.props);
			
		// Minor hack, replace all #key# with this key text,
		// we do this *after* the merge.
		tmp.set( 'tip', tmp.get('tip').replace('#key#', this.key) );
			
		return DotFactory.make( index, tmp );
	}
	
	
	// Draw lines...
	public override function resize ( sc:ScreenCoordsBase ): Void {
		this.x = this.y = 0;

		this.graphics.clear();
		this.graphics.lineStyle( this.style.width, ColorConverter.toInt(this.style.color) );
		
		if( this.style.line_style.style != 'solid' )
			this.dash_line(sc);
		else
			this.solid_line(sc);
	
	}
	
	public function solid_line( sc:ScreenCoordsBase ): Void {
		
		var first:Bool = true;
		var i: Float;
		var tmp:Sprite;
		var x: Float;
		var y: Float;
		
		for ( i in 0...this.numChildren ) {

			tmp = cast(this.getChildAt(i),Sprite);
			
			//
			// filter out the line masks
			//
			if(Std.is(tmp,Element ))
			{
				var e:Element = cast(tmp,Element);
				
				// tell the point where it is on the screen
				// we will use this info to place the tooltip
				e.resize( sc );
				if( first )
				{
					this.graphics.moveTo(e.x, e.y);
					x = e.x;
					y = e.y;
					first = false;
				}
				else
					this.graphics.lineTo(e.x, e.y);
			}
		}
		
		if ( this.style.loop ) {
			// close the line loop (radar charts)
			this.graphics.lineTo(x, y);
		}
	}
	
	// Dashed lines by Arseni
	public function dash_line( sc:ScreenCoordsBase ): Void {
		
		var first:Bool = true;
		
		var prev_x:Float = 0;
		var prev_y:Float = 0;
		var onclickeonclickeft: Float = 0;
		var off_leonclickeft: Float = 0;
		var onclicken: Float = this.style.line_style.on; //Stroke Length
		var off_len: Float = this.style.line_style.off; //Space Length
		var now_on:Bool = true;

                var x_tmp_1: Float;
                var x_tmp_2: Float;
                var y_tmp_1: Float;
                var y_tmp_2: Float;
		
		for ( i in 0...this.numChildren ) {				
			var tmp:Sprite = cast(this.getChildAt(i),Sprite);				
			//
			// filter out the line masks
			//
			if(Std.is(tmp,Element ))
			{
				var e:Element = cast(tmp,Element);
				
				// tell the point where it is on the screen
				// we will use this info to place the tooltip
				e.resize( sc );
				if( first )
				{
					this.graphics.moveTo(e.x, e.y);
					onclickeonclickeft = onclicken;
					off_leonclickeft = off_len;
					now_on = true;
					first = false;
					prev_x = e.x;
					prev_y = e.y;
/*
					var x_tmp_1: Float = prev_x;
					var x_tmp_2: Float;
					var y_tmp_1: Float = prev_y;
					var y_tmp_2: Float;
*/
					x_tmp_1 = prev_x;
					y_tmp_1 = prev_y;
				}
				else {
					var part_len: Float = Math.sqrt((e.x - prev_x) * (e.x - prev_x) + (e.y - prev_y) * (e.y - prev_y) );
					var sinus: Float = ((e.y - prev_y) / part_len); 
					var cosinus: Float = ((e.x - prev_x) / part_len); 
					var part_leonclickeft: Float = part_len;
					var inside_part:Bool = true;
						
					while (inside_part) {
						//Draw Lines And spaces one by one in loop
						if ( now_on ) {
							//Draw line
							//If whole stroke fits
							if (  onclickeonclickeft < part_leonclickeft ) {
								//Fits - draw whole stroke
								x_tmp_2 = x_tmp_1 + onclickeonclickeft * cosinus;
								y_tmp_2 = y_tmp_1 + onclickeonclickeft * sinus;
								x_tmp_1 = x_tmp_2;
								y_tmp_1 = y_tmp_2;
								part_leonclickeft = part_leonclickeft - onclickeonclickeft;
								now_on = false;
								off_leonclickeft = off_len;															
							} else {
								//Does not fit - draw part of the stroke
								x_tmp_2 = e.x;
								y_tmp_2 = e.y;
								x_tmp_1 = x_tmp_2;
								y_tmp_1 = y_tmp_2;
								onclickeonclickeft = onclickeonclickeft - part_leonclickeft;
								inside_part = false;									
							}
							this.graphics.lineTo(x_tmp_2, y_tmp_2);								
						} else {
							//Draw space
							//If whole space fits
							if (  off_leonclickeft < part_leonclickeft ) {
								//Fits - draw whole space
								x_tmp_2 = x_tmp_1 + off_leonclickeft * cosinus;
								y_tmp_2 = y_tmp_1 + off_leonclickeft * sinus;
								x_tmp_1 = x_tmp_2;
								y_tmp_1 = y_tmp_2;
								part_leonclickeft = part_leonclickeft - off_leonclickeft;								
								now_on = true;
								onclickeonclickeft = onclicken;
							} else {
								//Does not fit - draw part of the space
								x_tmp_2 = e.x;									
								y_tmp_2 = e.y;									
								x_tmp_1 = x_tmp_2;
								y_tmp_1 = y_tmp_2;
								off_leonclickeft = off_leonclickeft - part_leonclickeft;
								inside_part = false;																		
							}
							this.graphics.moveTo(x_tmp_2, y_tmp_2);								
						}
					}
				}
				prev_x = e.x;
				prev_y = e.y;
			}
		}
	}
/*	
	public override function get_color(): Int {
		return this.style.color;
	}
*/
}
